package com.uinnova.product.eam.workable.controller;

import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.*;
import com.uinnova.product.eam.workable.service.FlowableService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.repository.Deployment;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * o
 * 工作流接口
 *
 * @author lichong
 * @since 2022/2/22 16:32
 */
@Api(value = "工作流接口", tags = {"工作流接口"})
@RestController
@RequestMapping("/flowable")
@Slf4j
public class FlowableController implements FlowableFeign {

    @Autowired
    private FlowableService flowableService;

    @PostMapping("deployProcessDefinition")
    public DeployResponse deployProcessDefinition(String processDefinitionName, @RequestParam("files") MultipartFile[] files) {
        Assert.notNull(processDefinitionName, "流程定义名字不能为空");
        String bpmnProcessDefinitionName = null;
        InputStream bpmnProcessDefinition = null;
        String bpmnProcessDefinitionImageName = null;
        InputStream bpmnProcessDefinitionImage = null;

        for (MultipartFile file : files) {
            String originalFilename = file.getOriginalFilename();
            if (originalFilename != null) {
                if (originalFilename.endsWith("xml")) {
                    bpmnProcessDefinitionName = originalFilename;
                    try {
                        bpmnProcessDefinition = file.getInputStream();
                    } catch (IOException ioException) {
                        log.error("流程配置文件读取失败", ioException);
                        throw new RuntimeException("流程配置文件读取失败");
                    }
                } else if (originalFilename.endsWith("png")) {
                    bpmnProcessDefinitionImageName = originalFilename;
                    try {
                        bpmnProcessDefinitionImage = file.getInputStream();
                    } catch (IOException ioException) {
                        log.error("流程图片文件读取失败", ioException);
                        throw new RuntimeException("流程图片文件读取失败");
                    }
                }
            }
        }
        Assert.notNull(bpmnProcessDefinition, "流程定义文件不能为空");
        Deployment deployment = flowableService.deployProcessDefinition(processDefinitionName, bpmnProcessDefinitionName
                , bpmnProcessDefinition, bpmnProcessDefinitionImageName, bpmnProcessDefinitionImage);
        DeployResponse deployResponse = new DeployResponse();
        deployResponse.setId(deployment.getId());
        deployResponse.setKey(deployment.getKey());
        deployResponse.setDeployName(deployment.getName());
        deployResponse.setDeployTime(deployment.getDeploymentTime());
        return deployResponse;
    }

    /**
     * 开启一个流程
     *
     * @param processRequest 请求实体
     * @return
     */
    @ApiOperation(value = "开启一个流程", notes = "processDefinitionKey和uerId必填", httpMethod = "POST")
    @PostMapping("/startProcessBindAssignee")
    public PorcessResponse startProcessBindAssignee(@RequestBody ProcessRequest processRequest) {
        Assert.notNull(processRequest.getProcessDefinitionKey(), "流程定义key不能为空");
        Assert.notNull(processRequest.getProcessInstanceName(), "流程实例名称不能为空");
        Assert.notNull(processRequest.getUserId(), "流程任务审批人不能为空");
        Assert.notNull(processRequest.getOwner(), "流程任务发起人不能为空");
        Task task = flowableService.startProcessBindAssignee(processRequest);
        PorcessResponse porcessResponse = new PorcessResponse();
        porcessResponse.setProcessInstanceId(task.getProcessInstanceId());
        porcessResponse.setTaskId(task.getId());
        return porcessResponse;
    }

    /**
     * 删除流程实例
     *
     * @param processRequest
     */
    @ApiOperation(value = "删除流程实例", notes = "processDefinitionKey和uerId必填", httpMethod = "DELETE")
    @DeleteMapping("/deleteProcessInstanceByBusinessId")
    public void deleteProcessInstanceByBusinessId(@RequestBody ProcessRequest processRequest) {
        Assert.notNull(processRequest.getBusinessKey(), "业务主键不能为空");
        flowableService.deleteProcessBusinessId(processRequest.getBusinessKey(), processRequest.getDeleteReason());
    }

    @DeleteMapping("/deleteHistoryProcessInstanceById")
    public String deleteHistoryProcessInstanceById(String processInstanceId) {
        flowableService.deleteHistoryProcessInstanceById(processInstanceId);
        return "success";
    }

    /**
     * 根据用户id获取流程列表
     *
     * @param userId
     * @return
     */
    @ApiOperation(value = "根据用户id获取流程列表", notes = "uerId必填", httpMethod = "GET")
    @GetMapping("/getTaskByUserId")
    public PageEntityInfo<TaskResponse> getTaskListByUserId(String userId, Integer pageSize, Integer pageNum) {
        Assert.notNull(userId, "用户id不能为空");
        return flowableService.getTaskResponseListByUser(userId, pageNum, pageSize);
    }

    /**
     * 根据业务主键获取历史流程列表
     *
     * @param processRequest
     * @return 历史流程列表
     */
    @ApiOperation(value = "根据业务主键获取历史流程列表", notes = "BusinessKey和ProcessDefinitionKey必填", httpMethod = "GET")
    @PostMapping("/getTaskListByBusinessId")
    public List<PorcessResponse> getTaskListByBusinessId(@RequestBody ProcessRequest processRequest) {
        Assert.notNull(processRequest.getBusinessKey(), "业务主键不能为空");
        Assert.notNull(processRequest.getProcessDefinitionKey(), "审批类型不能为空");
        return flowableService.getTaskListByBusinessId(processRequest.getBusinessKey(), processRequest.getProcessDefinitionKey());
    }

    /**
     * 根据用户id获取已办任务列表
     *
     * @param userId
     * @return
     */
    @ApiOperation(value = "根据用户id获取流程列表", notes = "uerId必填", httpMethod = "GET")
    @GetMapping("/getDoneTaskByUserId")
    public PageEntityInfo<TaskResponse> getDoneTaskListByUserId(String userId, Integer pageSize, Integer pageNum) {
        Assert.notNull(userId, "用户id不能为空");
        return flowableService.getDoneTaskListByUserId(userId, pageSize, pageNum);
    }

    @GetMapping("/getDoneAllTask")
    public List<TaskResponse> getDoneAllTask() {
        return flowableService.getDoneAllTask();
    }

    @GetMapping("/getCurrentAllTask")
    public List<TaskResponse> getCurrentAllTask() {
        return flowableService.getCurrentAllTask();
    }

    /**
     * 根据用户id获取任务列表
     *
     * @param userRole
     * @return
     */
    @ApiOperation(value = "根据用户id获取流程列表", notes = "角色id必填", httpMethod = "GET")
    @GetMapping("/getTaskByUserRoleId")
    public List<TaskResponse> getTaskListByRoleId(String userRole) {
        Assert.notNull(userRole, "角色id不能为空");
        return flowableService.getTaskListByGroup(userRole);
    }

    /**
     * 根据用户角色获取任务列表
     *
     * @param userRoles
     * @return
     */
    @ApiOperation(value = "根据用户ids获取流程列表", notes = "角色id必填", httpMethod = "GET")
    @PostMapping("/getTaskByUserRoleIds")
    public List<TaskResponse> getTaskListByRoleIds(@RequestBody List<String> userRoles) {
        Assert.notNull(userRoles, "角色id不能为空");
        return flowableService.getTaskListByGroups(userRoles);
    }

    /**
     * 完成任务（执行审批结果）
     *
     * @param taskRequest
     * @return
     */
    @ApiOperation(value = "完成任务（执行审批结果）", notes = "任务id和审批结果不能为空", httpMethod = "POST")
    @PostMapping("/completeTask")
    public TaskResponse completeTask(@RequestBody TaskRequest taskRequest) {
        Assert.notNull(taskRequest.getTaskId(), "任务id不能为空");
        Assert.notNull(taskRequest.getAction(), "审批结果不能为空");
        return flowableService.completeTask(taskRequest);
    }

    @ApiOperation(value = "查询终止审批视图/方案，true则表示该数据已被终止，流程已经结束,false在流程中", notes = "", httpMethod = "GET")
    @GetMapping("/selectFlowStatus")
    public Boolean selectFlowStatus(@RequestParam String businessKey,@RequestParam String processDefinitionKey) {
        Assert.notNull(businessKey, "businessKey不能为空");
        Assert.notNull(processDefinitionKey, "processDefinitionKey不能为空");
        return flowableService.selectFlowStatus(businessKey,processDefinitionKey);
    }

    /**
     * 生成流程图文件流
     *
     * @param processInstanceId 流程实例
     */
    @ApiOperation(value = "生成流程图文件流", notes = "processInstanceId必填", httpMethod = "GET")
    @GetMapping("/genProcessDiagram")
    public String genProcessDiagram(String processInstanceId) {
        Assert.notNull(processInstanceId, "流程实例id不能为空");
        return flowableService.genProcessDiagramByProcessId(processInstanceId);
    }

    @ApiOperation(value = "判断流程是否结束", notes = "processInstanceId必填", httpMethod = "GET")
    @GetMapping("/processInstanceISExist")
    @Override
    public Boolean processInstanceISExist(String processInstanceId) {
        return flowableService.isExistProcIntRunning(processInstanceId);
    }

    @ApiOperation(value = "根据流程实例id获取流程实例信息", notes = "processInstanceId必填", httpMethod = "GET")
    @GetMapping("/getProcessInstanceByProcessInstanceId")
    @Override
    public PorcessResponse getProcessInstanceByProcessInstanceId(String processInstanceId) {
        return flowableService.getProcessInstanceByProcessInstanceId(processInstanceId);
    }

    @ApiOperation(value = "根据业务主键和流程定义key获取流程实例信息", notes = "businessId必填和流程定义key必填", httpMethod = "GET")
    @GetMapping("/getProcessInstanceByBusinessIdAndProcessDefinitionKey")
    @Override
    public PorcessResponse getProcessInstanceByBusinessIdAndProcessDefinitionKey(String businessId, String processDefinitionKey) {
        return flowableService.getProcessInstanceByBusinessIdAndProcessDefinitionKey(businessId, processDefinitionKey);
    }

    /**
     * 获取历史审核记录
     *
     * @param processInstanceId
     * @return
     */
    @GetMapping("/getHistoryTaskByCurrentProcessInstanceId")
    public List<HistoryTaskResponse> getHistoryTaskByCurrentProcessInstanceId(String processInstanceId) {
        Assert.notNull(processInstanceId, "流程实例id不能为空");
        return flowableService.getHistoryTaskDataByPorcessInstanceId(processInstanceId);
    }

    @GetMapping("/getCurrentTaskByCurrentProcessInstanceId")
    public List<TaskResponse> getCurrentTaskByCurrentProcessInstanceId(String processInstanceId) {
        Assert.notNull(processInstanceId, "流程实例id不能为空");
        return flowableService.getActiveTaskByProcessInstanceId(processInstanceId);
    }

    @GetMapping("/getTaskInfoByTaskId")
    @Override
    public TaskResponse getTaskInfoByTaskId(String taskId) {
        Assert.notNull(taskId, "任务id不能为空");
        return flowableService.getTaskInfoByTaskId(taskId);
    }

    @GetMapping("/getTaskCountByUserId")
    public long getTaskCountByUserId(String userId) {
        Assert.notNull(userId, "用户id不能为空");
        return flowableService.getTaskCountByUserId(userId);
    }

    @GetMapping("/getCurrentTaskDefinitionInfo")
    public TaskResponse getCurrentTaskDefinitionInfo(String businessKey, String processDefinitionKey) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(processDefinitionKey, "流程定义不能为空");
        return flowableService.getCurrentTaskDefinitionInfo(businessKey, processDefinitionKey);
    }

    @GetMapping("/getCurrentUserTask")
    public TaskResponse getCurrentUserTask(@RequestParam String businessKey, @RequestParam String processDefinitionKey,
                                           @RequestParam String userCode) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(processDefinitionKey, "流程定义不能为空");
        Assert.notNull(userCode, "当前人loginCode不能为空");
        return flowableService.getCurrentUserTask(businessKey, processDefinitionKey, userCode);
    }

    @GetMapping("/getCurrentUserActiveTask")
    public TaskResponse getCurrentUserActiveTask(@RequestParam String businessKey, @RequestParam String processDefinitionKey,
                                                 @RequestParam String userCode) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(processDefinitionKey, "流程定义不能为空");
        Assert.notNull(userCode, "当前人loginCode不能为空");
        return flowableService.getCurrentUserActiveTask(businessKey, processDefinitionKey, userCode);
    }

    @GetMapping("/getCurrentTaskAssignees")
    public TaskResponse getCurrentTaskAssignees(String businessKey, String processDefinitionKey) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(processDefinitionKey, "流程定义不能为空");
        return flowableService.getCurrentTaskAssignees(businessKey, processDefinitionKey);
    }


    /**
     * 获取当前流程存活的任务
     *
     * @param processInstanceId
     * @return
     */
    @ApiOperation(value = "根据用户ids获取流程列表", notes = "角色id必填", httpMethod = "GET")
    @GetMapping("/getActiveTaskByProcessInstanceId")
    public List<TaskResponse> getActiveTaskByProcessInstanceId(String processInstanceId) {
        Assert.notNull(processInstanceId, "processInstanceId");
        return flowableService.getActiveTaskByProcessInstanceId(processInstanceId);
    }

    /**
     * 根据流程实例id结束流程
     * @param processInstanceId
     * @param TerminationReason
     * @return
     */
    @GetMapping("/terminateProcessInstanceById")
    public Boolean terminateProcessInstanceById(@RequestParam String processInstanceId,@RequestParam(required = false) String TerminationReason) {
        Assert.notNull(processInstanceId, "processInstanceId");
        flowableService.terminateProcessInstanceById(processInstanceId,TerminationReason);
        return true;
    }

    @GetMapping("/getCurrentOwnerTask")
    public TaskResponse getCurrentOwnerTask(@RequestParam String businessKey, @RequestParam String userCode) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(userCode, "当前人loginCode不能为空");
        return flowableService.getCurrentOwnerTask(businessKey, userCode);
    }

    @GetMapping("/getCurrentOwnerActiveTask")
    public TaskResponse getCurrentOwnerActiveTask(@RequestParam String businessKey, @RequestParam String userCode) {
        Assert.notNull(businessKey, "业务主键不能为空");
        Assert.notNull(userCode, "当前人loginCode不能为空");
        return flowableService.getCurrentOwnerTask(businessKey, userCode);
    }

    @PostMapping("/getDoneTaskList")
    public List<TaskResponse> getDoneTaskList(@RequestParam String userId, @RequestBody List<String> processInstanceIds) {
        Assert.notNull(userId, "当前人loginCode不能为空");
        Assert.notEmpty(processInstanceIds, "流程实例不能为空");
        return flowableService.getDoneTaskList(userId, processInstanceIds);
    }

    @GetMapping("/isExistByTaskId")
    public Boolean isExistByTaskId(String taskId) {
        Assert.notNull(taskId, "任务id不能为空");
        return flowableService.isExistByTaskId(taskId);
    }


    @GetMapping("/suspendedTask")
    public Boolean suspendedTask(String taskId) {
        flowableService.suspendedTask(taskId);
        return true;
    }

    @PostMapping("/changeAssigness")
    public Boolean changeAssigness(TaskRequest request) {
        flowableService.changeAssigness(request);
        return true;
    }

    @PostMapping("/delegateTask")
    public Boolean delegateTask(TaskRequest request) {
        flowableService.delegateTask(request);
        return true;
    }

    @GetMapping("/resolveTask")
    public Boolean resolveTask(@RequestParam String taskId) {
        flowableService.resolveTask(taskId);
        return true;
    }

    @PostMapping("/listForArchReview")
    public List<TaskResponse> listForArchReview(@RequestBody ArchReviewTaskQueryReq req) {
        return flowableService.listForArchReview(req);
    }

    @PostMapping("/listForDiagram")
    public List<TaskResponse> listForDiagram(@RequestBody DiagramReviewTaskQueryReq req) {
        return flowableService.listForDiagram(req);
    }

    @GetMapping("/getAllDiagramInstance")
    public List<AllDiagramInstanceDto> getAllDiagramInstance() {
        return flowableService.getAllDiagramInstance();
    }
    @PostMapping("/getActiveSimpleTaskByProcessInstanceIds")
    public List<TaskResponse> getActiveSimpleTaskByProcessInstanceIds(@RequestBody List<String> processInstanceIds) {
        return flowableService.getActiveSimpleTaskByProcessInstanceIds(processInstanceIds);
    }

    @PostMapping("/queryActiveTaskByProcIdAndDes")
    public List<TaskResponse> queryActiveTaskByProcIdAndDes(@RequestBody ActiveTaskQueryReq req) {
        return flowableService.queryActiveTaskByProcIdAndDes(req);
    }
}
